#ifndef LOOPER_H
#define LOOPER_H

#include <mutex>
#include <thread>
#include <memory>
#include <atomic>
#include <functional>
#include <condition_variable>
#include "buffer.hpp"

namespace Log
{
    using Functor = std::function<void(Buffer &)>;
    
    enum class AsyncType {
        ASYNC_SAFE,     // 安全模式，缓存区满了就阻塞，避免资源耗尽的风险
        ASYNC_UNSAFE    // 不考虑资源耗尽的问题，无限扩容
    };
    
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor &cb, AsyncType loop_type = AsyncType::ASYNC_SAFE) : 
            _looper_type(AsyncType::ASYNC_SAFE),
            _callBack(cb), 
            _stop(false), 
            _thread(std::thread(&AsyncLooper::threadEntry, this)) { (void)loop_type; }

        ~AsyncLooper() { stop(); }

        void stop() 
        {
            _stop = true;
            _cond_con.notify_all();
            _thread.join();
        }

        void push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_looper_type == AsyncType::ASYNC_SAFE)
                _cond_pro.wait(lock, [&](){ return _pro_buf.wirteAbleSize() >= len; });
            _pro_buf.push(data, len);
            _cond_con.notify_one();
        }
    private:
        // 线程入口函数
        void threadEntry()
        {
            while (1)
            {
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    if (_stop && _pro_buf.empty())  break;
                    _cond_con.wait(lock, [&]() { return _stop || !_pro_buf.empty(); });
                    _con_buf.swap(_pro_buf);
                    if (_looper_type == AsyncType::ASYNC_SAFE)
                        _cond_pro.notify_all();
                }
                _callBack(_con_buf);
                _con_buf.reset();
            }
        }     
        private:
        AsyncType _looper_type;
        Functor _callBack;      // 对缓冲区数据处理的回调函数
        std::atomic<bool> _stop; // 停止标志
        Buffer _pro_buf;        // 生产者缓冲区
        Buffer _con_buf;        // 消费者缓冲区
        std::mutex _mutex;
        std::condition_variable _cond_pro;
        std::condition_variable _cond_con;
        std::thread _thread; // 异步工作器对应的工作线程
    };
}


#endif